#ifndef __PID_CONTROLLOR_H__
#define __PID_CONTROLLOR_H__

#include <cmath>
#include <iostream>
#include <chrono>
#include <ctime>    

class pid_ctl
{
public:
    pid_ctl() = default;

    pid_ctl(const std::string& name);

    ~pid_ctl() = default;

    float limit_abs(const float input, const float max);

    static float limit(const float input, const float max, const float min);

    void set_pid(const float p, const float i, const float d, const float int_limit = -1);

    void set_limit(const float max, const float min);

    void calculate(float& ouput, const float input, const float expect);

    void calculate(float& ouput, const float input, const float expect, const float input_derivative);

    void update_prev_err(const float err);

    float get_interval(void);

    std::string param_info(void);


    typedef struct _out_t
    {
        float p;
        float i;
        float d;
        _out_t(): p(0), i(0), d(0){}
        float sum(void){
            return p+i+d;
        }
        float sum(const float max, const float min){
            return pid_ctl::limit(p+i+d, max, min);
        }
    }out_t;
    
private:
    float kp_;
    float ki_;
    float kd_;
    float int_limit_;
    out_t out_;
    float prev_input_;
    float prev_err_ = 0;
    float out_max_ = 0;
    float out_min_ = 0;
    // float 
    std::string name_;
    std::chrono::time_point<std::chrono::system_clock> last_time_;
    // = ;
        // std::chrono::duration<double> diff = end-start;
};


#endif